package com.example.javaproject.design.rules;

/**
 * ### 依赖倒置原则(解耦)
 * <p>
 * 定义
 * 高层模块(调用方)不依赖于底层模块(被调用方)，两者应该依赖自抽象。抽象(接口或者抽象类)不应该依赖与细节(具体实现类)，细节应该依赖与抽象
 * 在java中抽象这里是说 接口或者抽象类，细节是说的它们的实现类，在设计的时候，引入抽象层，让彼此之间通过抽象层进行关联，当需求变更时通过新增实现类或者添加抽象方法来做到
 * 大大降低了高层模块与底层模块的耦合度。
 * <p>
 * 简而言之就是 面向抽象编程，这是实现"开闭原则"的基础
 * <p/>
 */
public class DIPTest {

    public static void main(String[] args) {
        // 例子  利用高压锅做饭：最开始的需求是 高压锅能做饭
        Rice rice = new Rice();
        Pot pot = new Pot();
        pot.cook(rice);

        // 跟随业务需求的变化，现在 要求高压锅，能煮大米，能顿排骨，能煲汤；之前的写法是 高压锅依赖大米，必须要更改高压锅结构才可以，所以那样设计是有问题的
        // 新的设计，引入抽象层，无论大米排骨汤都是食物，让高压锅去依赖食物，代码如下

        Pot1 p1 = new Pot1();
        Foot r1 = new Rice1();
        Foot ribs = new Ribs();
        Foot soup = new Soup();

        p1.cook(r1);
        p1.cook(ribs);
        p1.cook(soup);
    }

}

/**
 * 高压锅
 */
class Pot {
    public void cook(Rice rice) {
        rice.heating();
    }
}

/**
 * 大米
 */
class Rice {
    public void heating() {
        System.out.println("大米，煮1个小时就ok，很好吃");
    }
}

class Pot1 {
    public void cook(Foot foot) {
        foot.heating();
    }
}

interface Foot {
    void heating();
}

class Rice1 implements Foot {
    public void heating() {
        System.out.println("大米，煮1个小时就ok，很好吃");
    }
}

class Ribs implements Foot {
    public void heating() {
        System.out.println("排骨，需要炖1个小时就很香");
    }
}

class Soup implements Foot {
    public void heating() {
        System.out.println("煲汤，需要半小时老少咸宜");
    }
}